home *** CD-ROM | disk | FTP | other *** search
- Subject: Fmtr - simple text formatter
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 4, Issue 120
- Submitted by: harvard!hscfvax!popvax!mohamed (Mohamed ellozy)
-
-
- Fmtr is a simple text formatter which evens out the lines of
- files prepared for submission to the Unix formatters nroff,
- troff, or ditroff.
-
- It is for users who find editing neatly formatted files
- pleasanter than working with files with irregular lines. It
- knows that lines starting with a period or with an apostrophe
- should be output as is, and that certain requests and macros
- start no-fill mode, while others return to fill mode. So, unlike
- fmt, it will process the following example properly:
-
- .TS
- n n.
- 1 2
- 3 4
- .TE
-
- Fmt run on that example would produce:
-
- .TS
- n n. 1 2 3 4
- .TE
-
- destroying the table.
-
- Mohamed el Lozy mohamed@hscfvax.uucp
- Health Sciences Computing Facility ...!harvard!hscfvax!mohamed
- Harvard School of Public Health
- 665 Huntington Avenue
- Boston, MA 02115
-
- ------------------------------ CUT HERE ------------------------------
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # Makefile
- # command.c
- # efopen.3s
- # efopen.c
- # fgetsmod.3s
- # fgetsmod.c
- # fmtr.1
- # fmtr.c
- # fmtr.h
- # getopt.3
- # getopt.c
- # lowtext.c
- # This archive created: Thu May 15 16:20:30 1986
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'README'" '(1089 characters)'
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- The shell archive contains the files needed to make fmtr, a formatter
- for {n,t,dit}roff input files. Four of the source files:
-
- fmtr.h
- fmtr.c
- command.c
- lowtext.c
-
- contain the program proper. In addition it uses three functions that
- I have put in my library:
-
- getopt() a public domain version of the System V utility
- apparently due to Henry Spencer taht I have
- modified minimally
- efopen() a modified version of K & P's function
- fgetsmod() a modified version of fgets() that truncates
- lines longer than the array they are being read
- into.
-
- Manual pages for fmtr and for the three functions named above are
- included. The Makefile does not have any provision for adding these
- functions to any library. I have added them to /lib/libc.a, you may
- want to put them elsewhere. I have also not put in any provision for
- installing the manual pages associated with them.
-
- Comments, bug reports etc to:
-
- Mohamed el Lozy mohamed@hscfvax.uucp
- Health Sciences Computing Facility ...!harvard!hscfvax!mohamed
- Harvard School of Public Health
- 665 Huntington Avenue
- Boston, MA 02115
- SHAR_EOF
- if test 1089 -ne "`wc -c < 'README'`"
- then
- echo shar: error transmitting "'README'" '(should have been 1089 characters)'
- fi
- chmod +x 'README'
- fi
- echo shar: extracting "'Makefile'" '(789 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- cat << \SHAR_EOF > 'Makefile'
- CFLAGS = -O
-
- # comment out next line if you have getopt() in your library
- GETOPT = getopt.o
-
- # comment out next line if you have efopen() in your library
- EFOPEN = efopen.o
-
- # comment out next line if you have fgetsmod() in your library
- FGETSMOD = fgetsmod.o
-
- SRC = fmtr.c command.c lowtext.c efopen.c getopt.c fgetsmod.c
- OBJ = fmtr.o command.o lowtext.o $(EFOPEN) $(GETOPT) $(FGETSMOD)
-
- # You may wish to modify either or both of the following:
- BINDIR = /usr/local
- MANDIR = /usr/man/man1
-
- fmtr: $(OBJ)
- cc $(CFLAGS) -s -o fmtr $(OBJ)
-
- fmtr.o command.o lowtext.o: fmtr.h
-
- install: fmtr fmtr.1h
- cp -c fmtr $(BINDIR)
- cp -c fmtr.1h $(MANDIR)
-
- shar:
- shar -a README Makefile $(SRC) fmtr.h fmtr.1 efopen.3s \
- fgetsmod.3s getopt.3 > fmtr.shar
-
- clean:
- /bin/rm -f *.o a.out core fmtr fmtr.shar
- SHAR_EOF
- if test 789 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 789 characters)'
- fi
- chmod +x 'Makefile'
- fi
- echo shar: extracting "'command.c'" '(4522 characters)'
- if test -f 'command.c'
- then
- echo shar: will not over-write existing file "'command.c'"
- else
- cat << \SHAR_EOF > 'command.c'
- #ifndef lint
- static char rcsid[] = "$Header: command.c,v 1.4 86/05/05 14:08:32 root Exp $";
- #endif
-
- /* command.c decodes command. Uses binary search in array
- * of struct cmd.
- */
-
- #include "fmtr.h"
-
- #define HUGE 1000
- #define PLUS '+'
- #define MINUS '-'
-
- #define MAX(x,y) ((x) > (y) ? (x) : (y))
- #define MIN(x,y) ((x) < (y) ? (x) : (y))
-
- /* cmdtype is upper case version of command. All commands of
- * interest to us are either ce, ul, or else equivalent to
- * fi or nf
- */
-
- enum cmdtype
- {
- CE, UL, FI, NF, OTHER
- } cmd, getcmd();
-
- int len;
-
- struct cmd {
- char *name;
- enum cmdtype type;
- } cmd_table[50] = { "ce", CE, /* basic nroff requests */
- "ul", UL,
- "nf", NF,
- "fi", FI,
- "TS", NF, /* universal macros */
- "TE", FI,
- "EQ", NF,
- "EN", FI,
- "PS", NF,
- "PE", FI,
- "IS", NF,
- "IE", FI,
- "DS", NF, /* ms macros */
- "ID", NF,
- "CD", NF,
- "LD", NF,
- "DE", FI,
- "(b", NF, /* me macros */
- ")b", FI,
- "(c", NF,
- ")c", FI,
- "(l", NF,
- ")l", FI,
- "(z", NF,
- ")z", FI,
- (char *) NULL, OTHER
- };
-
- int val; /* both are set in getval() */
- char argtype; /* and used in setparam() */
-
- /* command() takes a line starting with some form of the command start
- * sequence (period or apostrophe, optionally preceded by \&), and
- * calls getcmd() to return an integer representing the command name,
- * and then takes appropriate action.
- *
- * In all cases it produces a break and prints out the command line as is.
- */
-
- command(line)
- char line[];
- {
- cmd = getcmd(line);
-
- if (cmd != OTHER)
- switch (cmd) {
- case CE:
- getval(line); /* only need getval() with CE and UL */
- ce_val = setparam(ce_val, 1, 0, HUGE);
- break;
- case UL:
- getval(line);
- ul_val = setparam(ul_val, 1, 0, HUGE);
- break;
- case NF:
- nf_val = 1;
- break;
- case FI:
- nf_val = 0;
- break;
- }
-
- n_brk();
- puts(line);
- }
-
- enum cmdtype getcmd(line) /* gets command type by binary search */
- char *line; /* stolen from K & R p. 125 with minor changes */
- {
- int high, low, mid, cond;
- char *cp;
-
- low = 0;
- high = len - 1;
-
- cp = (*line == '\\') ? line + 3 : line + 1;
-
- while (low <= high) {
- mid = (low + high)/2;
- if ((cond = strncmp(cp, cmd_table[mid].name, 2)) < 0)
- high = mid - 1;
- else if (cond > 0)
- low = mid + 1;
- else
- return(cmd_table[mid].type);
- }
- return(OTHER);
- }
-
- mk_table(sarray, earray)
- char *sarray, *earray;
- {
- int mycmp();
- char *cp, *malloc(), *strncpy();
- struct cmd *cmdptr;
-
- if (len == 0) { /* find end */
- cmdptr = cmd_table;
- while (cmdptr->name)
- cmdptr++; /* now pointing to NULL ending defined */
- len = cmdptr - cmd_table;
- }
- else
- cmdptr = cmd_table + len;
-
- if (sarray)
- for (cp = sarray; *cp; cp += 3) {
- cmdptr->name = malloc(3);
- (void) strncpy(cmdptr->name, cp + 1, 2);
- cmdptr->type = NF;
- cmdptr++;
- }
-
- if (earray)
- for (cp = earray; *cp; cp += 3) {
- cmdptr->name = malloc(3);
- (void) strncpy(cmdptr->name, cp + 1, 2);
- cmdptr->type = FI;
- cmdptr++;
- }
-
- len = cmdptr - cmd_table;
-
- qsort((char *) cmd_table, len, sizeof cmd_table[0], mycmp);
- }
-
- mycmp(s1, s2)
- struct cmd *s1, *s2;
- {
- return(strcmp(s1->name, s2->name));
- }
-
- /* getval() gets value of argument preceded by optional sign. Here
- we are following the nroff rules: commands are exactly two
- letters long followed by optional spaces before arguments. */
-
- getval(line)
- char *line;
- {
- char *cp;
-
- if (*line == '\\') /* don't test for z_flag, since otherwise */
- cp = line + 5; /* we would not be here */
- else
- cp = line + 3;
- for ( ; isspace(*cp); *cp++)
- ;
- argtype = *cp;
- if (argtype == PLUS || argtype == MINUS)
- cp++;
- val = atoi(cp);
- }
-
- /* setparam() sets parameter. May be set to param if present and legal,
- * otherwise to def_val, if absent, less than min_val or greater than
- * max_val.
- */
-
- setparam(param, def_val, min_val, max_val)
- int param, def_val, min_val, max_val;
- {
- if (argtype == '\0')
- return(def_val);
- else if (argtype == PLUS)
- param += val;
- else if (argtype == MINUS)
- param -= val;
- else
- param = val;
- param = MAX(param, min_val);
- param = MIN(param, max_val);
-
- return(param);
- }
-
- #ifdef DEBUG
- print_tab() /* prints table, useful while debugging */
- {
- struct cmd *cmdptr;
-
- for (cmdptr = cmd_table; cmdptr < cmd_table + len; cmdptr++)
- printf("%s\n", cmdptr->name);
- }
- #endif
- SHAR_EOF
- if test 4522 -ne "`wc -c < 'command.c'`"
- then
- echo shar: error transmitting "'command.c'" '(should have been 4522 characters)'
- fi
- chmod +x 'command.c'
- fi
- echo shar: extracting "'efopen.3s'" '(918 characters)'
- if test -f 'efopen.3s'
- then
- echo shar: will not over-write existing file "'efopen.3s'"
- else
- cat << \SHAR_EOF > 'efopen.3s'
- .TH EFOPEN 3S "11 May 1986"
- .SH NAME
- efopen \- open a stream, exiting with message in case of failure
- .SH SYNOPSIS
- .B #include <stdio.h>
- .br
- .B extern char *progname;
- .PP
- .SM
- .B FILE
- .B *efopen(filename, type)
- .br
- .B char *filename, *type;
- .SH DESCRIPTION
- .I Efopen
- calls
- .IR fopen (3S)
- to open the file named by
- .IR filename ,
- and if successful returns a pointer to be used to identify the stream in
- subsequent operations.
- .PP
- If
- .I filename
- is the string \-
- .I efopen
- will return
- .IR stdin .
- .PP
- .I Type
- is a character string as in
- .IR fopen (3S).
- .PP
- On failure,
- .I efopen
- exits, after printing out the name of the program (if a value has been
- given to
- .B progname
- by main), the name of the file, and calling
- .IR perror (3).
- .SH "SEE ALSO"
- fopen(3S),
- open(2),
- fclose(3)
- .SH "AUTHOR"
- Modified by Mohamed el Lozy from program given in
- .I "The UNIX Programming Environment"
- by Brian W. Kernighan and Rob Pike, p 182.
- SHAR_EOF
- if test 918 -ne "`wc -c < 'efopen.3s'`"
- then
- echo shar: error transmitting "'efopen.3s'" '(should have been 918 characters)'
- fi
- chmod +x 'efopen.3s'
- fi
- echo shar: extracting "'efopen.c'" '(591 characters)'
- if test -f 'efopen.c'
- then
- echo shar: will not over-write existing file "'efopen.c'"
- else
- cat << \SHAR_EOF > 'efopen.c'
- #ifndef lint
- static char rcsid[] = "$Header: efopen.c,v 1.3 86/05/11 09:50:48 root Exp $";
- #endif
-
- #include <stdio.h>
-
- FILE *
- efopen(file, mode) /* fopen file, die if cannot */
- char *file, *mode; /* from K & P with addition of perror() and handling
- of "-" as stdin */
- {
- FILE *fp;
- extern char *progname;
-
- if (strcmp(file, "-") == 0)
- return(stdin);
-
- if ((fp = fopen(file, mode)) != NULL)
- return (fp);
-
- if (progname)
- fprintf(stderr, "%s ", progname);
- fprintf(stderr, "can't open file %s mode %s: ", file, mode);
- perror("");
- exit(1);
- /* NOTREACHED */
- }
- SHAR_EOF
- if test 591 -ne "`wc -c < 'efopen.c'`"
- then
- echo shar: error transmitting "'efopen.c'" '(should have been 591 characters)'
- fi
- chmod +x 'efopen.c'
- fi
- echo shar: extracting "'fgetsmod.3s'" '(1470 characters)'
- if test -f 'fgetsmod.3s'
- then
- echo shar: will not over-write existing file "'fgetsmod.3s'"
- else
- cat << \SHAR_EOF > 'fgetsmod.3s'
- .TH FGETSMOD 3S "11 May 1986"
- .SH NAME
- fgetsmod \- get a line from a stream, truncating it if it is too long
- .SH SYNOPSIS
- .B #include <stdio.h>
- .br
- .B #define TOOLONG -2
- .PP
- .B int *fgets(s, n, stream)
- .br
- .B char *s;
- .br
- .SM
- .B FILE
- .B *stream;
- .SH DESCRIPTION
- .I Fgetsmod
- is a modified version of
- .IR fgets ,
- which truncates lines longer than the size of the array
- into which they are being read. It reads
- .IR n \-2
- characters, or up to a newline
- character, whichever comes first,
- from the
- .I stream
- into the string
- .IR s .
- If no newline is found after reading the first
- .IR n \-2
- characters,
- .I fgetsmod
- will add a newline and null character, then
- read and discard characters from the
- input stream up to a newline. In other words, it
- will discard characters in excess of the
- capacity of
- .IR s .
- The last character read into
- .I s
- is followed by a null character.
- .I Fgetsmod
- returns the number of characters read
- if it can read the whole line.
- .SH "SEE ALSO"
- gets(3S),
- puts(3S),
- getc(3S),
- scanf(3S),
- fread(3S),
- ferror(3S)
- .SH AUTHOR
- Mohamed el Lozy, Harvard Health Sciences Computing Faility
- .SH DIAGNOSTICS
- .I Fgetsmod
- return the integer zero
- upon end of file or read error.
- It returns \-2 (to avoid confusion with
- .BR \s9EOF\s0 )
- if the line is too long.
- .SH BUGS
- .I Fgetsmod
- returns an
- .IR int ,
- unlike
- .IR fgets ,
- which returns a
- .IR char .
- It should therefore probably return
- .SM
- .B EOF
- on end of file, but returning zero makes it
- more similar to
- .IR fgets .
- SHAR_EOF
- if test 1470 -ne "`wc -c < 'fgetsmod.3s'`"
- then
- echo shar: error transmitting "'fgetsmod.3s'" '(should have been 1470 characters)'
- fi
- chmod +x 'fgetsmod.3s'
- fi
- echo shar: extracting "'fgetsmod.c'" '(1683 characters)'
- if test -f 'fgetsmod.c'
- then
- echo shar: will not over-write existing file "'fgetsmod.c'"
- else
- cat << \SHAR_EOF > 'fgetsmod.c'
- #ifndef lint
- static char rcsid[] = "$Header: fgetsmod.c,v 1.3 86/05/05 14:19:17 root Exp $";
- #endif
-
- #include <stdio.h>
-
- #define TOOLONG -2
-
- /* New and improved version of fgets. Unlike original, eats up extra chars.
- * fgets1 will read n - 1 characters, or up to a new line, whichever
- * comes first, from stream iop into string s. The last character read
- * into s is followed by a null character.
- *
- * It deals with all possibilities. If line ends with newline or have
- * isolated EOF, no problem. Otherwise, it will insert a newline and eat
- * any excess characters. Hence guarantees line ending with newline
- * followed by null.
- *
- * It returns:
- * 1. NULL at end of file, for compatible with fgets.
- * 2. TOOLONG if line is too long.
- * This is usable as a warning.
- * 3. Length of line, excluding null (like strlen), otherwise.
- * This is useful in the usual case when line is read uneventfully.
- */
-
- fgetsmod(s, n, iop)
- char *s;
- register FILE *iop;
- {
- register c;
- register char *cs;
-
- cs = s;
-
- while (--n > 0 && (c = getc(iop)) != EOF) {
- *cs++ = c;
- if (c == '\n')
- break;
- }
-
- if (c == '\n') { /* normal ending, commonest case */
- *cs = '\0';
- return (cs - s);
- }
-
- if ((c == EOF) && (cs == s)) /* isolated EOF, second commonest case */
- return (NULL);
-
- if (n == 0) { /* line too long */
- *cs = '\0';
- *(--cs) = '\n'; /* put in missing newline */
- while ((c = getc(iop)) != EOF && c != '\n') /* eat up extra chars */
- ;
- return (TOOLONG);
- }
-
- if (c == EOF) { /* final line has no newline -- rare */
- *cs++ = '\n';
- *cs = '\0';
- return (cs - s); /* pretend all was OK */
- }
- /* NOTREACHED */
- }
- SHAR_EOF
- if test 1683 -ne "`wc -c < 'fgetsmod.c'`"
- then
- echo shar: error transmitting "'fgetsmod.c'" '(should have been 1683 characters)'
- fi
- chmod +x 'fgetsmod.c'
- fi
- echo shar: extracting "'fmtr.1'" '(3397 characters)'
- if test -f 'fmtr.1'
- then
- echo shar: will not over-write existing file "'fmtr.1'"
- else
- cat << \SHAR_EOF > 'fmtr.1'
- .TH FMTR 1H LOCAL "4th Berkeley Distribution"
- .SH NAME
- fmtr \- simple formatter for
- .I roff
- source files
- .SH SYNOPSIS
- .B fmtr
- [ \-w
- .I width
- ] [ \-z ] [ \-s
- .I .s1.s2.s3 ... .sn
- ] [ \-e
- .I .e1.e2.e3 ... .en
- ] [ name ... ]
- .SH DESCRIPTION
- .I Fmtr
- is a simple text formatter which evens out the lines of files prepared
- for submission to the Unix formatters
- .IR nroff ,
- .IR troff ,
- or
- .IR ditroff .
- .PP
- It is for users who find editing neatly formatted files pleasanter than
- working with files with irregular lines. It knows that lines starting
- with a period or with an apostrophe should be output as is, and that
- certain requests and macros start no-fill mode, while others return to
- fill mode. So, unlike
- .IR fmt ,
- it will process the following example properly:
- .sp
- .in +5
- .nf
- Some short lines
- to be joined,
- then a table which should be respected:
- \&.TS
- n n.
- 1 2
- 3 4
- \&.TE
- .nf
- More short
- lines to be joined.
- .in
- .sp
- .fi
- The above will produce:
- .sp
- .nf
- .in +5
- Some short lines to be joined, then a table which should be respected:
- \&.TS
- n n.
- 1 2
- 3 4
- \&.TE
- More short lines to be joined.
- .fi
- .sp
- .in
- .I Fmt
- run on that example would produce:
- .sp
- .in +5
- .nf
- Some short lines to be joined, then a table which should be respected:
- \&.TS
- n n. 1 2 3 4
- \&.TE
- More short lines to be joined.
- .fi
- .in
- .sp
- destroying the table.
- .PP
- .I Fmtr
- reads the concatenation of input files (or standard input if none are
- given) and produces on standard output a version of its input with lines
- as close as possible to 72 characters. This default line length may be
- modified with the
- .IR \-w
- (for width) flag. If you specify the
- .I \-z
- flag it will peek under a zero width character at the start of a line
- seeking a command.
- .I Fmtr
- knows about the
- .IR ms (7)
- and
- .IR me (7)
- macro packages.
- .PP
- Since
- .I fmtr
- knows and respects most formatter constructs, it can be safely used on
- an entire document, as long as that document does not contain any
- strange sequences of commands.
- .PP
- There are two ways in which additional macros that start or end no-fill
- mode may be specified to
- .IR fmtr .
- The
- .I \-s
- and
- .I \-e
- flags can be used to introduce sequences of macros that start and end
- no-fill mode respectively. Any number of macros, each of which must
- consist of a period followed by exactly two letters, can be concatenated
- into a string. So if you are using two macros,
- .I .OS
- and
- .IR .FS ,
- both of which start no-fill mode, and a corresponding pair,
- .I .OE
- and
- .IR .FE ,
- which end no-fill mode, you would enter
- .sp
- .ti +5
- .I "fmtr -s .OS.FS -e .OE.FE file"
- .sp
- For users who regularly use macros of there own, the environmental
- variables
- .I FMTR_S
- and
- .I FMTR_E
- are taken as strings of macros which start and end no-fill mode. They
- should be in the same format as the strings used as arguments to the
- .I \-s
- and
- .I \-e
- flags.
- .SH "SEE ALSO"
- nroff(1), environ(7), ms(7), me(7)
- .SH AUTHOR
- Mohamed el Lozy, Health Sciences Computing Facility, Harvard School of
- Public Health
- .SH BUGS
- The program does not attempt to duplicate
- .IR fmt ,
- and will not deal with mail headers or with indented (preformatted)
- text.
- .br
- The current version does not support the
- .I mm
- macros, I hope to correct that soon.
- .br
- Macros recognized must be exactly two characters long.
- .br
- .I Fmtr
- is not a full
- .I roff
- recognizer. For example, changing the definition of the control or the
- escape character, will cause confusion.
- SHAR_EOF
- if test 3397 -ne "`wc -c < 'fmtr.1'`"
- then
- echo shar: error transmitting "'fmtr.1'" '(should have been 3397 characters)'
- fi
- chmod +x 'fmtr.1'
- fi
- echo shar: extracting "'fmtr.c'" '(3468 characters)'
- if test -f 'fmtr.c'
- then
- echo shar: will not over-write existing file "'fmtr.c'"
- else
- cat << \SHAR_EOF > 'fmtr.c'
- #ifndef lint
- static char rcsid[] = "$Header: fmtr.c,v 1.4 86/05/05 14:09:41 root Exp $";
- #endif
-
- /* fmtr, a formatter for roff source text respecting no fill mode.
- * The code is derived from a translation to C of Kernighan and
- * Plaugher's format program.
- */
-
- #include "fmtr.h"
-
- int optind, opterr;
- char *optarg, *progname; /* program name */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i, c;
- char *sarray, *earray, *getenv();
- FILE *efopen(), *fp;
-
- progname = argv[0];
- outp = outbuf;
- sarray = earray = (char *) NULL;
- llength = 72; /* default */
-
- sarray = getenv("FMTR_S");
- check(sarray, "environmental variable FMTR_S");
- earray = getenv("FMTR_E");
- check(earray, "environmental variable FMTR_E");
-
- mk_table(sarray, earray); /* make table of commands from env var */
- /* we call mk_table whether the arrays */
- /* null or not */
- sarray = earray = (char *) 0;
-
- while ((c = getopt(argc, argv, "zw:s:e:")) != EOF)
- switch (c) {
- case 'z':
- z_flag = 1;
- break;
- case 'w':
- llength = atoi(optarg);
- if (llength <= 0 || llength >= BUFSIZ - 2) {
- fprintf(stderr,"%s: bad line length: %s\n", progname, optarg);
- exit (1);
- }
- break;
- case 's':
- sarray = optarg;
- check(sarray, "-s flag");
- break;
- case 'e':
- earray = optarg;
- check(earray, "-e flag");
- break;
- case '?':
- usage();
- exit(1);
- }
-
- mk_table(sarray, earray); /* make table of commands from flags */
- /* again, always call */
-
- argc -= optind;
- argv += optind;
-
- fp = stdin;
- i = 0;
- do {
- if (argc > 0)
- fp = efopen(*argv, "r");
- do_fmt(fp); /* does real work */
- argv++;
- } while (++i < argc);
-
- n_brk();
- }
-
- check(string, origin) /* check format of string of macros */
- char *string, *origin;
- {
- if (string == NULL)
- return;
- if ((string[0] != '.') || strlen(string) % 3 != 0) {
- fprintf(stderr,
- "%s: list of macros '%s' supplied with %s is not in correct format\n",
- progname, string, origin);
- exit(1);
- }
- }
-
- /* do_fmt is where work is done, or rather assigned. Each line
- * read has the terminatig newline, and any trailing blanks, removed.
- * Then it is sent to either command() or text(), depending on whether
- * it appears to be a command or not.
- */
-
- do_fmt(fp)
- FILE *fp;
- {
- char *cp, line[10*BUFSIZ];
- int length;
-
- while (length = fgetsmod(line, sizeof line, fp)) {
- for (cp = &line[length - 2]; *cp == ' ' && cp >= line; cp--)
- ;
- *++cp = '\0';
- if (*line == '.' || *line == '\'' ||
- (z_flag && strncmp(line, "\\&.", 3) == 0) ||
- (z_flag && strncmp(line, "\\&'", 3) == 0))
- command(line);
- else
- text(line);
- }
- }
-
- /* text() checks for leading blanks or blank line, in which case causes
- * break. Blank lines output as is, others broken into words by getword()
- * with words sent to outbuf by putword().
- */
-
- text(line)
- char *line;
- {
- char *pline, wordbuf[BUFSIZ], *getword();
-
- if (ul_val || ce_val || nf_val) {
- puts(line);
- if (ul_val)
- ul_val--;
- if (ce_val)
- ce_val--;
- return;
- }
-
- if (*line == ' ' || *line == '\0')
- leadbl(line);
- if (*line == '\0')
- put(line);
- else { /* main case */
- pline = line;
- do {
- pline = getword(pline, wordbuf);
- if (pline)
- putword(wordbuf);
- } while (pline);
- }
- }
-
- usage()
- {
- fprintf(stderr,
- "usage: %s [ -z ] [ -wn ] [ -s start_string ] [ -e end_string] [ file ... ]\n",
- progname);
- }
- SHAR_EOF
- if test 3468 -ne "`wc -c < 'fmtr.c'`"
- then
- echo shar: error transmitting "'fmtr.c'" '(should have been 3468 characters)'
- fi
- chmod +x 'fmtr.c'
- fi
- echo shar: extracting "'fmtr.h'" '(365 characters)'
- if test -f 'fmtr.h'
- then
- echo shar: will not over-write existing file "'fmtr.h'"
- else
- cat << \SHAR_EOF > 'fmtr.h'
- #include <stdio.h>
- #include <ctype.h>
-
- int z_flag; /* look behind zero width spaces? */
- int nf_val; /* no fill on or off? */
- int ul_val; /* number of lines to underline */
- int ce_val; /* number of lines to center */
- int llength;
-
- char outbuf[BUFSIZ]; /* output buffer, ridiculously large */
- char *outp; /* pointer into outbuf */
-
- void n_brk();
- char *strcpy();
- SHAR_EOF
- if test 365 -ne "`wc -c < 'fmtr.h'`"
- then
- echo shar: error transmitting "'fmtr.h'" '(should have been 365 characters)'
- fi
- chmod +x 'fmtr.h'
- fi
- echo shar: extracting "'getopt.3'" '(2749 characters)'
- if test -f 'getopt.3'
- then
- echo shar: will not over-write existing file "'getopt.3'"
- else
- cat << \SHAR_EOF > 'getopt.3'
- .TH GETOPT 3
- .DA 25 March 1982
- .SH NAME
- getopt \- get option letter from argv
- .SH SYNOPSIS
- .ft B
- int getopt(argc, argv, optstring)
- .br
- int argc;
- .br
- char **argv;
- .br
- char *optstring;
- .sp
- extern char *optarg;
- .br
- extern int optind;
- .ft
- .SH DESCRIPTION
- .I Getopt
- returns the next option letter in
- .I argv
- that matches a letter in
- .IR optstring .
- .I Optstring
- is a string of recognized option letters;
- if a letter is followed by a colon, the option is expected to have
- an argument that may or may not be separated from it by white space.
- .I Optarg
- is set to point to the start of the option argument on return from
- .IR getopt .
- .PP
- .I Getopt
- places in
- .I optind
- the
- .I argv
- index of the next argument to be processed.
- Because
- .I optind
- is external, it is normally initialized to zero automatically
- before the first call to
- .IR getopt .
- .PP
- When all options have been processed (i.e., up to the first
- non-option argument),
- .I getopt
- returns
- .BR EOF .
- The special option
- .B \-\-
- may be used to delimit the end of the options;
- .B EOF
- will be returned, and
- .B \-\-
- will be skipped.
- .SH SEE ALSO
- getopt(1)
- .SH DIAGNOSTICS
- .I Getopt
- prints an error message on
- .I stderr
- and returns a question mark
- .RB ( ? )
- when it encounters an option letter not included in
- .IR optstring .
- .SH EXAMPLE
- The following code fragment shows how one might process the arguments
- for a command that can take the mutually exclusive options
- .B a
- and
- .BR b ,
- and the options
- .B f
- and
- .BR o ,
- both of which require arguments:
- .PP
- .RS
- .nf
- main(argc, argv)
- int argc;
- char **argv;
- {
- int c;
- extern int optind;
- extern char *optarg;
- \&.
- \&.
- \&.
- while ((c = getopt(argc, argv, "abf:o:")) != EOF)
- switch (c) {
- case 'a':
- if (bflg)
- errflg++;
- else
- aflg++;
- break;
- case 'b':
- if (aflg)
- errflg++;
- else
- bproc();
- break;
- case 'f':
- ifile = optarg;
- break;
- case 'o':
- ofile = optarg;
- break;
- case '?':
- default:
- errflg++;
- break;
- }
- if (errflg) {
- fprintf(stderr, "Usage: ...");
- exit(2);
- }
- for (; optind < argc; optind++) {
- \&.
- \&.
- \&.
- }
- \&.
- \&.
- \&.
- }
- .RE
- .PP
- A template similar to this can be found in
- .IR /usr/pub/template.c .
- .SH HISTORY
- Written by Henry Spencer, working from a Bell Labs manual page.
- Behavior believed identical to the Bell version.
- .SH BUGS
- It is not obvious how
- `\-'
- standing alone should be treated; this version treats it as
- a non-option argument, which is not always right.
- .PP
- Option arguments are allowed to begin with `\-';
- this is reasonable but reduces the amount of error checking possible.
- .PP
- .I Getopt
- is quite flexible but the obvious price must be paid: there is much
- it could do that it doesn't, like
- checking mutually exclusive options, checking type of
- option arguments, etc.
- SHAR_EOF
- if test 2749 -ne "`wc -c < 'getopt.3'`"
- then
- echo shar: error transmitting "'getopt.3'" '(should have been 2749 characters)'
- fi
- chmod +x 'getopt.3'
- fi
- echo shar: extracting "'getopt.c'" '(1608 characters)'
- if test -f 'getopt.c'
- then
- echo shar: will not over-write existing file "'getopt.c'"
- else
- cat << \SHAR_EOF > 'getopt.c'
- #ifndef lint
- static char rcsid[] = "$Header: getopt.c,v 1.3 86/05/05 14:20:35 root Exp $";
- #endif
-
- /* got this off net.sources */
- #include <stdio.h>
-
- /*
- * get option letter from argument vector
- */
- int opterr = 1, /* if set to zero no message for bad option */
- optind = 1, /* index into parent argv vector */
- optopt; /* character checked for validity */
- char *optarg; /* argument associated with option */
-
- #define BADCH (int)'?'
- #define EMSG ""
-
- getopt(nargc,nargv,ostr)
- int nargc;
- char **nargv,
- *ostr;
- {
- static char *place = EMSG; /* option letter processing */
- register char *oli; /* option letter list index */
- char *index();
-
- if(!*place) { /* update scanning pointer */
- if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
- return(EOF);
- if (*place == '-') { /* found "--" */
- ++optind;
- return(EOF);
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
- if(!*place) ++optind;
- if (opterr)
- fprintf(stderr, "%s: illegal option -- %c\n", *nargv, optopt);
- return(BADCH);
- }
- if (*++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place) ++optind;
- }
- else { /* need an argument */
- if (*place) optarg = place; /* no white space */
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- if (opterr)
- fprintf(stderr, "%s: option requires an argument -- %c\n",
- *nargv, optopt);
- return(BADCH);
- }
- else optarg = nargv[optind]; /* white space */
- place = EMSG;
- ++optind;
- }
- return(optopt); /* dump back option letter */
- }
- SHAR_EOF
- if test 1608 -ne "`wc -c < 'getopt.c'`"
- then
- echo shar: error transmitting "'getopt.c'" '(should have been 1608 characters)'
- fi
- chmod +x 'getopt.c'
- fi
- echo shar: extracting "'lowtext.c'" '(2420 characters)'
- if test -f 'lowtext.c'
- then
- echo shar: will not over-write existing file "'lowtext.c'"
- else
- cat << \SHAR_EOF > 'lowtext.c'
- #ifndef lint
- static char rcsid[] = "$Header: lowtext.c,v 1.3 86/04/25 17:15:14 root Exp $";
- #endif
-
- #include "fmtr.h"
-
- int ti_val;
-
- /* leadbl() deals with leading blanks, causes break, then sets
- * ti_val to number of blanks, unless line is blank. Then pulls
- * line forewards, so text() now has line starting with text, with
- * ti_val containing the needed indent.
- */
-
- leadbl(line)
- char *line;
- {
- char *ip;
-
- n_brk();
-
- ip = line;
- while (*ip == ' ')
- ip++;
- if (*ip != '\n')
- ti_val += ip - line;
- (void) strcpy(line, ip);
- }
-
- /* n_brk() causes a break */
-
- void n_brk()
- {
- if (outp > outbuf) {
- outp--; /* back off from EOS */
- while (*outp == ' ' && outp >= outbuf) /* remove trailing blanks */
- outp--;
- *++outp = '\0';
- put(outbuf);
- }
- outp = outbuf;
- }
-
- /*
- * getword gets the next word plus trailing space
- * from the array pointed to by pline and
- * returns it in that pointed at by word. If there are
- * no further words on that line, it returns NULL.
- * It returns a pointer to the start of the next word.
- */
-
- char *getword(pline, word)
- char *pline, *word;
- {
- if (*pline == '\0') {
- *word = '\0';
- return(NULL);
- }
-
- while (*pline != ' ' && *pline != '\0') {
- if (*pline == '\\' && isspace(pline[1])) /* get escaped space in word */
- *word++ = *pline++;
- *word++ = *pline++;
- }
-
- /* get trailing spaces, and guarantee spaces at end of line;
- * normally one but two at end of sentence.
- */
-
- if (*pline == '\0') {
- char *cptmp = pline;
-
- *word++ = ' ';
- while (any(*--cptmp, "\"']})"))
- ;
- if (any(*cptmp, ".:!?"))
- *word++ = ' ';
- }
- while (*pline == ' ')
- *word++ = *pline++;
- *word = '\0';
- return(pline);
- }
-
- putword(word) /* put word into output buffer */
- char *word;
- {
- int s, t; /* not needed, but greatly simplify if */
-
- t = strlen(word) - 1; /* -1 for one trailing blank */
- s = outp - outbuf;
- if (s + t <= llength - ti_val) {
- for (; *word; *outp++ = *word++)
- ;
- return;
- }
- n_brk();
- for (; *word; *outp++ = *word++)
- ;
- }
-
- put(line) /* output routine, separate as is more complex in original */
- char *line;
- {
- int i;
-
- for (i = 1; i <= ti_val; i++)
- putchar(' ');
- ti_val = 0;
- puts(line);
- }
-
- any(ch, string) /* returns true if character is in string */
- char ch;
- char *string;
- {
- while (*string)
- if (ch == *string++)
- return(1);
- return(0);
- }
- SHAR_EOF
- if test 2420 -ne "`wc -c < 'lowtext.c'`"
- then
- echo shar: error transmitting "'lowtext.c'" '(should have been 2420 characters)'
- fi
- chmod +x 'lowtext.c'
- fi
- exit 0
- # End of shell archive
-